/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package co.edu.unitecnologica.procesos;

import co.edu.unitecnologica.modelo.Activaciones;
import co.edu.unitecnologica.modelo.ActivacionesPK;
import co.edu.unitecnologica.modelo.Conceptos;
import co.edu.unitecnologica.modelo.ConceptosActivaciones;
import co.edu.unitecnologica.modelo.ConceptosActivacionesPK;
import co.edu.unitecnologica.modelo.ConceptosLiquidaciones;
import co.edu.unitecnologica.modelo.Estudiantes;
import co.edu.unitecnologica.modelo.Grupos;
import co.edu.unitecnologica.modelo.Liquidaciones;
import co.edu.unitecnologica.modelo.Programas;
import co.edu.unitecnologica.modelo.VariacionesConceptosPeriodos;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;

/**
 *
 * @author osalcedo
 */
public class GerenciaElectronica {
    private EntityManager em;
    private int entidad;
    private File archivo;
    private int periodo;
    private String usuario;
    private String logErrores;
    private String detalleError;

    public GerenciaElectronica(EntityManager e, File file, int ent, int p, String u){
        em=e;
        entidad=ent;
        periodo=p;
        archivo=file;
        logErrores="";
        detalleError="";
        usuario=u;

    }

    public boolean procesar(){
        BufferedReader in = null;
        boolean hecho=true;
        int nroLinea=0;
        String t;
        try {
            in = new BufferedReader(new InputStreamReader(new FileInputStream(archivo)));
            String linea;
            String valor = null;
            String fecha_pago = null;
            String cod_telnet = null;
            while ((linea = in.readLine())!=null) {
              StringTokenizer tokens= new java.util.StringTokenizer(linea,"\t");
              int j=1;
              while(tokens.hasMoreTokens()){
                  t=tokens.nextToken();
                  switch(j){
                      case 1:
                          cod_telnet=t.substring(0, t.length()-1);
                          break;
                      case 2:
                          fecha_pago=t;
                          break;
                      case 3:
                          valor=t;
                  }
                  j++;
              }
              nroLinea++;
               if(cod_telnet==null || fecha_pago==null ||valor==null){
                   hecho=false;
                   logErrores+="Linea "+nroLinea+": Error de formato en alguna de los campos.\n";
               }
              if(!generarActivacion(cod_telnet,fecha_pago,Double.parseDouble(valor))){
                  hecho=false;
                  logErrores+="Linea "+nroLinea+": Referencia "+cod_telnet+" no procesada: "+detalleError+".\n";
              }
            }
            in.close();
            return hecho;
        } catch (Exception ex) {
            Logger.getLogger(GerenciaElectronica.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        } 
    }

    /**
     * @return the logErrores
     */
    public String getLogErrores() {
        return logErrores;
    }

    /**
     * @param logErrores the logErrores to set
     */
    public void setLogErrores(String logErrores) {
        this.logErrores = logErrores;
    }

    private boolean generarActivacion(String cod_telnet, String fecha_pago, double valor) {
        try {
            TypedQuery<Estudiantes> query = em.createNamedQuery("Estudiantes.findByCodTelnet", Estudiantes.class);
            query.setParameter("codTelnet", cod_telnet);
            List<Estudiantes> list = query.getResultList();
            Liquidaciones liquidacion = null;
            boolean activado_prev = false;
            DateFormat format = new java.text.SimpleDateFormat("dd/MM/yyyy");
            Date fecha = format.parse(fecha_pago);
            if(list.size()==0){
                if(cod_telnet.startsWith("2013")&& cod_telnet.length()>=9){
                    String formulario=cod_telnet.substring(6);
                    query.setParameter("codTelnet", formulario);
                    list = query.getResultList();
                    if(list.size()==0){
                        detalleError="referencia no encontrada";
                        return false;
                    }
                }
                else{
                    detalleError="referencia no encontrada";
                    return false;
                }
            }
            for (int i = 0; i < list.size(); i++) {
                Estudiantes estudiante = list.get(i);
                Collection<Liquidaciones> liquidaciones = estudiante.getLiquidacionesCollection();
                Iterator<Liquidaciones> it_liquidaciones = liquidaciones.iterator();
                int secuencia = 0;
                while (it_liquidaciones.hasNext()) {
                    Liquidaciones l = it_liquidaciones.next();
                    if (l.getLiquidacionesPK().getCodPeriodo() == periodo) {
                        if (l.getEstado().compareTo("liquidado") == 0) {
                            if (secuencia < l.getLiquidacionesPK().getSecuencia()) {
                                secuencia = l.getLiquidacionesPK().getSecuencia();
                                liquidacion = l;
                            }
                        } else {
                            activado_prev = true;
                            break;
                        }
                    }
                }
                if (activado_prev) {
                    detalleError="referencia activada previamente";
                    return false;
                }
                else{
                    //verifica si tiene conceptos de activacion manual
                    if(liquidaciones!=null){
                        Collection<ConceptosLiquidaciones> coleccion;
                        Iterator<ConceptosLiquidaciones> iterador;
                        ConceptosLiquidaciones cl;
                        Conceptos c;
                        coleccion=liquidacion.getConceptosLiquidacionesCollection();
                        iterador=coleccion.iterator();
                        while(iterador.hasNext()){
                            cl=iterador.next();
                            c=cl.getConceptos();
                            if(c.getActivacionManual()=='Y'){
                                detalleError="referencia tiene "+c.getDescripcion()+" causal de activacion manual";
                                return false;
                            }
                        }
                    }
                    boolean vlcoincide=false;
                    if(liquidacion!=null){
                        for (int creditos = 0; creditos <= liquidacion.getEstudiantes().getProgramas().getCreditosTotales(); creditos++) {
                            if(getTotalPagar(liquidacion, creditos, fecha)==valor){
                                vlcoincide=true;
                                Conceptos conceptoEntidad=em.getReference(Conceptos.class, entidad);
                                Programas programa=em.getReference(Programas.class, liquidacion.getLiquidacionesPK().getCodPrograma());
                                em.getTransaction().begin();
                                    em.refresh(liquidacion);
                                    Activaciones activacion= new Activaciones();
                                    ActivacionesPK pk= new ActivacionesPK();
                                    pk.setCodPeriodo(liquidacion.getLiquidacionesPK().getCodPeriodo());
                                    pk.setCodPrograma(liquidacion.getLiquidacionesPK().getCodPrograma());
                                    pk.setIdEstudiante(liquidacion.getLiquidacionesPK().getIdEstudiante());
                                    pk.setSecuencia(liquidacion.getLiquidacionesPK().getSecuencia());
                                    activacion.setActivacionesPK(pk);
                                    activacion.setLiquidaciones(liquidacion);
                                    activacion.setCreditos(creditos);
                                    activacion.setValor(valor);
                                    activacion.setFechaActivacion(fecha);
                                    activacion.setFechaActividad(Calendar.getInstance().getTime());
                                    activacion.setHoraActividad(Calendar.getInstance().getTime());
                                    activacion.setUsuario(usuario);
                                    liquidacion.setEstado("activado");
                                    em.persist(activacion);
                                em.getTransaction().commit();
                                em.getTransaction().begin();
                                    ConceptosActivaciones ce= new ConceptosActivaciones();
                                    ConceptosActivacionesPK cpk= new ConceptosActivacionesPK();
                                    cpk.setCodConcepto(entidad);
                                    cpk.setCodPeriodo(liquidacion.getLiquidacionesPK().getCodPeriodo());
                                    cpk.setCodPrograma(liquidacion.getLiquidacionesPK().getCodPrograma());
                                    cpk.setIdEstudiante(liquidacion.getLiquidacionesPK().getIdEstudiante());
                                    cpk.setSecuencia(liquidacion.getLiquidacionesPK().getSecuencia());
                                    cpk.setFechaPago(fecha);
                                    ce.setConceptosActivacionesPK(cpk);
                                    ce.setActivaciones(activacion);
                                    ce.setValor(valor);
                                    //registrando informacion contable
                                    if(conceptoEntidad.getCodAuxiliar()!=null)
                                        ce.setCodAuxiliar(conceptoEntidad.getCodAuxiliar());
                                    else
                                        ce.setCodAuxiliar(programa.getCodAuxiliar());
                                    if(conceptoEntidad.getCentroCosto()!=null)
                                        ce.setCentroCosto(conceptoEntidad.getCentroCosto());
                                    else
                                        ce.setCentroCosto(programa.getCentroCosto());
                                    if(conceptoEntidad.getNit()!=null)
                                        ce.setNit(conceptoEntidad.getNit());
                                    else
                                        ce.setNit(programa.getNit());
                                    ce.setTipoCuenta(conceptoEntidad.getTipoCuenta());
                                    ce.setNumeroCuenta(conceptoEntidad.getNumeroCuenta());
                                    ce.setFechaActividad(Calendar.getInstance().getTime());
                                    ce.setHoraActividad(Calendar.getInstance().getTime());
                                    ce.setUsuario(usuario);
                                    em.persist(ce);
                                em.getTransaction().commit();
                                return true;
                            }
                        }
                        if(!vlcoincide){
                            detalleError="Valor no coincide";
                            return false;
                        }
                    }
                    else{
                        detalleError="No tiene registro de liquidacion";
                        return false;
                    }
                }
            }
            return true;
        } catch (Exception ex) {
            detalleError="Excepcion: "+ex.getLocalizedMessage();
            return false;
        }
    }

    private double getTotalPagar(Liquidaciones liquidacion, int creditos, Date fecha){
        double valor=0.0;
        double porcentaje=0.0;
        Conceptos conceptoMatricula = null;
        boolean esAntiguo=true;
        boolean tieneDescuentos=false;
        Estudiantes estudiante = liquidacion.getEstudiantes();
        Programas programa=estudiante.getProgramas();
        if(estudiante.getCodTipoEstudiante().getCod().equals("N")||estudiante.getCodTipoEstudiante().getCod().equals("T"))
            esAntiguo=false;
        Collection<ConceptosLiquidaciones> conceptosLiquidacion = liquidacion.getConceptosLiquidacionesCollection();
        Iterator<ConceptosLiquidaciones> iteradorConceptos = conceptosLiquidacion.iterator();
        while(iteradorConceptos.hasNext()){
            ConceptosLiquidaciones conceptoliq = iteradorConceptos.next();
            if(conceptoliq.getConceptos().getCod()!=1){ //conceptos diferentes a matricula
                if(conceptoliq.getConceptos().getModoCalculo()=='P'){
                    if(conceptoliq.getValor()<0)
                        tieneDescuentos=true;
                    porcentaje+=conceptoliq.getValor()+getPorcentajeVariacionConcepto(liquidacion, conceptoliq.getConceptos(), fecha);
                }
                else
                    valor+=conceptoliq.getValor()*(1+getPorcentajeVariacionConcepto(liquidacion,conceptoliq.getConceptos(), fecha)/100);
            }
            else
                conceptoMatricula=conceptoliq.getConceptos();
        }
        double valor_base=getValorMatricula(liquidacion)*creditos/programa.getCreditosTotales();
        double total=0.0;
        double extemporanea=0.0;
        if(tieneDescuentos){
            if(getPorcentajeVariacionConcepto(liquidacion,conceptoMatricula, fecha)>0) //variacion extemporanea
                extemporanea+= getPorcentajeVariacionConcepto(liquidacion,conceptoMatricula, fecha);
            total= valor_base*(1+extemporanea/100)*(1.0+porcentaje/100.0); //no aplica variacion de matricula
        }
        else
            total= valor_base*(1.0+(porcentaje+getPorcentajeVariacionConcepto(liquidacion, conceptoMatricula, fecha))/100.0);
        total+=valor;
        return (double)Math.round(total);
    }

    private double getPorcentajeVariacionConcepto(Liquidaciones liquidacion, Conceptos concepto,Date fecha){
        Iterator<VariacionesConceptosPeriodos> itVariaciones = this.getVariacionesConceptos(liquidacion).iterator();
        double porcentaje=0.0;
        while(itVariaciones.hasNext()){
            VariacionesConceptosPeriodos v = itVariaciones.next();
            if(fecha.after(v.getFechaDesde())&&fecha.before(v.getFechaHasta())&&v.getVariacionesConceptosPeriodosPK().getCodPeriodo()==liquidacion.getLiquidacionesPK().getCodPeriodo()){
                if(concepto.equals(v.getConceptos())){
                    porcentaje+=v.getPorcentaje();
                }
            }
        }
        return porcentaje;
    }

     private double getValorMatricula(Liquidaciones liquidacion){
        Collection<ConceptosLiquidaciones> conceptosLiquidacion = liquidacion.getConceptosLiquidacionesCollection();
        Iterator<ConceptosLiquidaciones> iteradorConceptos = conceptosLiquidacion.iterator();
        while(iteradorConceptos.hasNext()){
            ConceptosLiquidaciones concepto = iteradorConceptos.next();
            if(concepto.getConceptos().getCod()==1) //concepto de matricula
                return concepto.getValor();
        }
        return 0.0;
    }

     private Collection<VariacionesConceptosPeriodos> getVariacionesConceptos(Liquidaciones liquidacion){
         Estudiantes e=liquidacion.getEstudiantes();
         String sql="select f_dar_grupo('"+e.getEstudiantesPK().getId()
            +"','"+e.getEstudiantesPK().getCodPrograma()+"') from dual";
         Query q = em.createNativeQuery(sql);
         int grupo=Integer.parseInt(q.getSingleResult().toString());
         Grupos g=em.getReference(Grupos.class, grupo);
         return g.getVariacionesConceptosPeriodosCollection();
     }
}
